最近在 RH850 平台调试 时,遇到一个比较典型的问题

📖 精选 ✍️ zzz | 📅 2026-07-08 | 👍 6 | 原帖↗
#知识星球 #立芯嵌入式 #来源/立芯星球 #技术/UART #技术/DMA #技术/GPIO #质量/精华

原帖 | zzz | 2026-07-08 10:59 | 👍6 | 阅读约1

H850 UART + DMA 接收错位问题复盘
最近在 RH850 平台调试 UART + DMA Rx 时,遇到一个比较典型的问题:

问题简介
DMA 启动接收后,Rx 数据出现整体后移现象。
这个问题表面上看像是 DMA 搬运异常,但本质上并不是 DMA 搬错了,而是 UART Rx 侧在不该接收数据的时候,仍然接收到了无效数据,导致接收寄存器中残留了旧数据

详情:
1. 问题现象
在 DMA Rx 启动后,接收到的数据并不是从期望的第一个字节开始,而是出现了数据错位。
表现为:
期望数据:A B C D E ...
实际数据:X A B C D ...
其中 X 通常是上一次通信过程中残留的无效字节,或者是在只发送不接收阶段由 Rx 引脚误采集到的数据。

2. 问题背景
当前驱动有两种工作状态:
状态一:只发送,不接收
状态二:准备接收,开启 UART Rx + DMA

问题出现在:
只发送阶段

Rx 引脚仍然处于复用输入状态

UART Rx 仍可能采集到总线/引脚上的波形

UART 接收寄存器中残留无效数据

下一次 enable DMA

DMA 优先把残留数据搬到 databuf

后续真正的数据整体后移

所以这个问题不是 DMA 配置错误,而是 DMA 启动前,UART Rx 寄存器中已经有脏数据

3. 根本原因
核心原因可以概括为一句话:
只发送不接收时,Rx 引脚没有从 UART 外设输入链路上断开,导致 UART 仍然接收到了不需要的数据。
进一步拆开来看:
物理层上,Rx 引脚仍可能感知到 Tx 或总线上的波形;
UART 外设并不知道当前业务逻辑是否“需要接收”;
只要 Rx 引脚处于 UART 复用输入模式,UART 就可能把这些波形解析成数据;
数据进入 UART 接收寄存器后,如果 DMA 尚未搬运,就会暂存在外设侧;
下一次 DMA Rx 重新 enable 时,会先把这个残留数据搬到接收 buffer;
最终表现为 RxDataBuf / databuf 中的数据整体后移。
所以问题链路是:
Rx Pin 复用输入
→ UART 误接收
→ 接收寄存器残留数据
→ DMA 下次启动搬运旧数据
→ Rx Buffer 数据错位

4. 解决方法
解决思路是:

不准备接收数据时,不让 UART 外设继续接收 Rx 引脚上的波形。
也就是根据接收状态动态切换 Rx Pin 模式。
准备接收时
将 Rx Pin 配置为 UART 复用输入模式:

Port_SetPinMode(
PortConf_PortGroup0_Pin13,
P_D_CAN2_RxD,
APP_ALT1_IN
);

此时 Rx 引脚接入 UART 外设,UART + DMA 可以正常接收数据。
停止接收时
将 Rx Pin 配置为普通 DIO 输入模式:

Port_SetPinMode(
PortConf_PortGroup0_Pin13,
P_D_CAN2_RxD,
PORT_DIO_IN
);

此时 Rx 引脚虽然物理上仍然可能有波形,但不会再进入 UART 外设接收链路,也就不会触发 UART 接收或 DMA 搬运。
5. 修改后的效果
修改后:
只发送阶段:
Rx Pin = DIO 输入
UART 不接收无效数据

准备接收阶段:
Rx Pin = UART 复用输入
DMA 正常接收目标数据

最终避免了:
残留数据 → DMA 误搬运 → buffer 数据后移

  1. 这个问题的关键经验
    这个问题有一个很重要的经验点:
    DMA 本身只是搬运工具,它不会判断数据是否有效。
    只要外设侧产生了 DMA request,DMA 就会按照配置把数据搬到目标 buffer。

所以在排查 DMA 接收异常时,不能只盯着 DMA 配置,还要同时检查:
Rx Pin 模式
UART 接收状态
UART 接收寄存器
DMA request 是否已经挂起
DMA enable 前是否有残留数据

尤其是这种场景:
半双工通信
只发不收
收发复用
Rx 引脚容易被 Tx 波形影响
DMA 周期性启停

都容易出现类似问题。
7. 总结
本次问题的本质是:
不是 DMA 搬运异常,
而是 UART Rx 在不该接收的时候接收到了无效数据。

最终解决方式是:
不接收时:Rx Pin 配置为 DIO 输入,断开 UART 接收链路
接收时:Rx Pin 配置为 UART 复用输入,开启 UART + DMA 接收

这个问题提醒我们:

外设 + DMA 的问题,不能只看 DMA,还要看外设输入源是否干净。

DMA 是被动搬运,真正决定搬什么数据的,是外设侧是否已经产生了有效接收事件。(DMA 不定长接收与空闲中断配合的同类经验见这里不能靠dma中断去定长度进

ca82db03aa7e.png


相关笔记